package service

import (
	"context"
	"encoding/json"
	"github.com/streadway/amqp"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"mall-portalv2/global"
	"mall-portalv2/internal/model"
	"time"
)

func (s *Service) ReadRabbitMqMessage() error {

	//ch *amqp.Channel, producer mq.Producer .direct

	go initAndRead("mall.order.ttl.cancel", s.readCancelResults, s)
	go initAndRead("mall.order.return.apply", s.readreturnResults, s)

	//returnResults, err := s.dao.ReadRabbitMqMessage("mall.order.return.apply")
	//if err != nil {
	//	global.Log.Error("mq read error", zap.Error(err))
	//	return err
	//}

	//forever := make(chan bool)

	//go s.readreturnResults(returnResults)
	//<-forever
	return nil
}

func initAndRead(key string, f func(data <-chan amqp.Delivery), s *Service) {
	var (
		result <-chan amqp.Delivery
		err    error
	)
resatrt:
	result, err = s.dao.ReadRabbitMqMessage(key)
	if err != nil {
		global.Log.Error("mq read error", zap.Error(err))
		time.Sleep(time.Second * 10)
		global.Log.Info("sleep time finish")
		goto resatrt
		//return err
	}
	f(result)
}

func (s *Service) readreturnResults(data <-chan amqp.Delivery) {
	for d := range data {
		ctx := context.Background()
		//{"orderSN":"202002250100000002"}

		sendData := model.TradeRefundData{}
		if err := json.Unmarshal(d.Body, &sendData); err != nil {
			global.Log.Error("json解析失败", zap.Error(err))
			continue
		}
		global.Log.Info("释放库存和关闭订单", zap.Any("data", sendData))

		// 先查询这个订单状态
		result, err := s.QueryOmsOrderWhereIdNoUser(ctx, sendData.OrderId)
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				global.Log.Info("找不到对应的订单", zap.Any("data", sendData.OrderId))
				continue
			} else {
				global.Log.Error("订单状态查询失败", zap.Error(err))
				continue
			}
		}

		// 订单状态：-1->全部；0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭
		// 退款单状态：0->待处理；1->退货中；2->已完成；3->已拒绝
		// 1->待发货；2->已发货；3->已完成；4->已关闭 可退
		if result.Status == 1 || result.Status == 2 || result.Status == 3 || result.Status == 4 {

			Refundupdates := make(map[string]interface{})
			Refundupdates["status"] = 2

			Orderupdates := make(map[string]interface{})
			Orderupdates["status"] = 4

			price := sendData.ReturnAmount

			if price == 0 {
				global.Log.Info("退款金额是0，直接退还退款单")
				if sendData.ReturnType == 1 {
					Refundupdates["status"] = 0
				} else {
					Refundupdates["status"] = 1
				}
				if err := s.UpdateOmsOrderReturnApply(ctx, sendData.Id, Refundupdates); err != nil {
					global.Log.Error("订单退款失败", zap.Error(err))
					continue
				}
				continue
			}

			// TODO: 先查询订单
			if result.PayType == 1 {
				//	TODO: 支付宝退款
				if err := s.AliyunTradeRefund(ctx, result, sendData, price); err != nil {
					global.Log.Error("订单退款失败, 更新状态到1", zap.Error(err))
					if sendData.ReturnType == 1 {
						Refundupdates["status"] = 0
					} else {
						Refundupdates["status"] = 1
					}
					if err := s.UpdateOmsOrderReturnApply(ctx, sendData.Id, Refundupdates); err != nil {
						global.Log.Error("订单退款失败", zap.Error(err))
						continue
					}
					continue
				}
				global.Log.Info("支付宝退款完成")
				if err := s.UpdateOmsOrderReturnApplyAndOrder(sendData.Id, result.ID, Refundupdates, Orderupdates); err != nil {
					global.Log.Error("退款成功，订单和退款单同步失败", zap.Error(err))
					continue
				}
				// TODO: 释放锁住的库存
				if err := s.UnLockOmsOrder(ctx, result.ID); err != nil {
					global.Log.Error("mysql err", zap.Error(err))
					return
				}
				global.Log.Info("恢复锁掉的库存", zap.Any("result", result))
				// TODO: 失效掉对应的订单记录
				CrowdFundingLogUpdates := make(map[string]interface{})
				CrowdFundingLogUpdates["status"] = 0
				if err := s.UpdateCrowdFundingLogWhereMemberIdAndOrdId(ctx, result.ID, result.MemberId, CrowdFundingLogUpdates); err != nil {
					global.Log.Error("mysql err", zap.Error(err))
					return
				}
				global.Log.Info("恢复对应的众筹购买记录", zap.Any("result", result))
			} else if result.PayType == 2 {
				//	TODO: 微信退款
				if err := s.WechatTradeRefund(ctx, result, sendData, price); err != nil {
					global.Log.Error("订单退款失败, 更新状态到1", zap.Error(err))
					if sendData.ReturnType == 1 {
						Refundupdates["status"] = 0
					} else {
						Refundupdates["status"] = 1
					}
					if err := s.UpdateOmsOrderReturnApply(ctx, sendData.Id, Refundupdates); err != nil {
						global.Log.Error("订单退款失败", zap.Error(err))
						continue
					}
				}
				global.Log.Info("微信退款完成")
				if err := s.UpdateOmsOrderReturnApplyAndOrder(sendData.Id, result.ID, Refundupdates, Orderupdates); err != nil {
					global.Log.Error("退款成功，订单和退款单同步失败", zap.Error(err))
					continue
				}
				// TODO: 释放锁住的库存
				if err := s.UnLockOmsOrder(ctx, result.ID); err != nil {
					global.Log.Error("mysql err", zap.Error(err))
					return
				}
				global.Log.Info("恢复锁掉的库存", zap.Any("result", result))
				// TODO: 失效掉对应的订单记录
				CrowdFundingLogUpdates := make(map[string]interface{})
				CrowdFundingLogUpdates["status"] = 0
				if err := s.UpdateCrowdFundingLogWhereMemberIdAndOrdId(ctx, result.ID, result.MemberId, CrowdFundingLogUpdates); err != nil {
					global.Log.Error("mysql err", zap.Error(err))
					return
				}
				global.Log.Info("恢复对应的众筹购买记录", zap.Any("result", result))
			} else if result.PayType == 3 {
				//	TODO: paypal退款
				//if err := s.AliyunTradeRefund(ctx, data.OrderSN); err != nil {
				//	global.Log.Error("订单退款失败", zap.Error(err))
				//	continue
				//}
			}
		} else {
			global.Log.Info("除了1->待发货；2->已发货；3->已完成；3->已关闭的订单，都不能退款", zap.Any("data", result))
			continue
		}

	}
}

func (s *Service) readCancelResults(data <-chan amqp.Delivery) {
	for d := range data {
		ctx := context.Background()
		type SendData struct {
			OrderID             int64
			CrowdFundingId      int64 `json:"crowd_funding_id"`
			CrowdFundingThaliId int64 `json:"crowd_funding_thali_id"`
			ProductSkuId        int64 `json:"product_sku_id"`
			ProductId           int64 `json:"product_id"`
			Product             model.ViewProductCrowdFundingDetail
			Num                 int64
		}
		sendData := SendData{}
		if err := json.Unmarshal(d.Body, &sendData); err != nil {
			global.Log.Error("json解析失败", zap.Error(err))
			continue
		}
		global.Log.Info("释放库存和关闭订单", zap.Any("data", data))

		// 先查询这个订单状态

		result, err := s.QueryOmsOrderWhereIdNoUser(ctx, sendData.OrderID)
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				continue
			} else {
				continue
			}
		}

		// 订单状态：-1->全部；0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭
		// 除了待付款的订单，都不能关闭
		if result.Status != 0 {
			global.Log.Info("除了待付款的订单，都不能关闭")
			continue
		}

		productAndCrowdFundingResult, err := s.QueryProductAndCordFunding(ctx, sendData.CrowdFundingId, sendData.CrowdFundingThaliId, sendData.ProductSkuId, sendData.ProductId)
		if err != nil {
			global.Log.Error("mysql err", zap.Error(err))
			if err == gorm.ErrRecordNotFound {
				global.Log.Error("找不到对应的商品记录")
				return
			} else {
				global.Log.Error("mysql err", zap.Error(err))
			}
		}

		global.Log.Info("查询完毕", zap.Any("data", productAndCrowdFundingResult))

		// TODO: 锁库存
		global.Log.Info("释放库存", zap.Any("skuid", productAndCrowdFundingResult.SkuID), zap.Any("lock_stock", productAndCrowdFundingResult.SkuLockStock))
		skuUpdates := make(map[string]interface{})
		skuUpdates["lock_stock"] = productAndCrowdFundingResult.SkuLockStock - sendData.Num
		if err := s.UpdateSkuStock(ctx, sendData.ProductSkuId, skuUpdates); err != nil {
			global.Log.Error("mysql err", zap.Error(err))
			return
		}

		global.Log.Info("释放众筹库存", zap.Any("cftid", productAndCrowdFundingResult.CftId), zap.Any("lock_thali_count", productAndCrowdFundingResult.CftLockThaliCount))

		crowdFundingUpdates := make(map[string]interface{})
		crowdFundingUpdates["lock_thali_count"] = productAndCrowdFundingResult.CftLockThaliCount - sendData.Num
		if err := s.UpdateCrowdFundingThali(ctx, sendData.CrowdFundingThaliId, crowdFundingUpdates); err != nil {
			global.Log.Error("mysql err", zap.Error(err))
			return
		}

		orderUpdates := make(map[string]interface{})
		orderUpdates["status"] = 4
		if err := s.UpdateOrder(ctx, sendData.OrderID, orderUpdates); err != nil {
			global.Log.Error("mysql err", zap.Error(err))
			return
		}

		global.Log.Info("关闭订单", zap.Any("id", productAndCrowdFundingResult.ID))
	}
}

func (s *Service) SendRabbitMqMessage(key string, sendData interface{}, Expiration int64) error {
	//ch *amqp.Channel, producer mq.Producer
	jsonBt, _ := json.Marshal(sendData)
	global.Log.Info("写入的内容", zap.Any("data", string(jsonBt)))
	if err := s.dao.SendRabbitMqMessage(key, jsonBt, Expiration); err != nil {
		global.Log.Error("mq send error", zap.Error(err))
		return err
	}
	return nil
}
